package com.panfeng.xcloud.boss.provider.member.security.password;

import com.panfeng.xcloud.boss.provider.member.security.SecurityConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * 自定义security密码登录过滤器
 *
 * @author xiaobo
 * @version 1.0
 * @since 2018-12-28
 */
@Slf4j
public class PwdAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

	private static final String POST = "POST";

	private String accountNumberParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_ACCOUNTNUMBER;
	private String passwordParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_PASSWORD;

	private String clientIdParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_CLIENTID;
	private String clientSecretParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_CLIENTSECRET;

	private boolean postOnly = true;

	public PwdAuthenticationFilter() {
		super(new AntPathRequestMatcher(SecurityConstants.DEFAULT_PWD_LOGIN_URL, "POST"));
	}

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
			throws AuthenticationException {
		if (postOnly && !POST.equals(request.getMethod())) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		}
		log.info(">>>> 开始执行PwdAuthenticationFilter过滤器，开始获取鉴权信息<<<");
		String grantType = getGrantType(request);
		if (StringUtils.isEmpty(grantType)) {
			grantType = "";
		}
		String accountNumber = getAccountNumber(request);
		if (StringUtils.isEmpty(accountNumber)) {
			accountNumber = "";
		}
		String password = getPassword(request);
		if (StringUtils.isEmpty(password)) {
			password = "";
		}
		String clientId = getClientId(request);
		if (StringUtils.isEmpty(clientId)) {
			clientId = "";
		}
		String clientSecret = getClientSecret(request);
		if (StringUtils.isEmpty(clientSecret)) {
			clientSecret = "";
		}
		grantType = grantType.trim();
		accountNumber = accountNumber.trim();
		password = password.trim();
		clientId = clientId.trim();
		clientSecret = clientSecret.trim();
		PwdAuthenticationToken authRequest = new PwdAuthenticationToken(grantType + "_" + accountNumber + "_" + password +"_"+ clientId +"_" + clientSecret);
		log.info(">>>> 已经执行PwdAuthenticationFilter过滤器完毕，PwdAuthenticationToken信息：{}<<<",authRequest);
		setDetails(request, authRequest);
		return this.getAuthenticationManager().authenticate(authRequest);
	}

	private String getGrantType(HttpServletRequest request) {
		return request.getParameter("grant_type");
	}

	private String getClientSecret(HttpServletRequest request) {
		return request.getParameter(clientSecretParameter);
	}

	private String getClientId(HttpServletRequest request) {
		return request.getParameter(clientIdParameter);
	}

	protected String getAccountNumber(HttpServletRequest request) {
		return request.getParameter(accountNumberParameter);
	}

	protected String getPassword(HttpServletRequest request) {
		return request.getParameter(passwordParameter);
	}

	protected void setDetails(HttpServletRequest request, PwdAuthenticationToken authRequest) {
		authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
	}

	public String getAccountNumberParameter() {
		return accountNumberParameter;
	}

	public void setAccountNumberParameter(String accountNumberParameter) {
		Assert.hasText(accountNumberParameter, "用户账号(手机号或者邮箱)信息参数没有设置accountNumber");
		this.accountNumberParameter = accountNumberParameter;
	}

	public String getPasswordParameter() {
		return passwordParameter;
	}

	public void setPasswordParameter(String passwordParameter) {
		Assert.hasText(accountNumberParameter, "用户密码参数没有设置password");
		this.passwordParameter = passwordParameter;
	}

	public String getClientIdParameter() {
		return clientIdParameter;
	}

	public void setClientIdParameter(String clientIdParameter) {
		Assert.hasText(clientIdParameter, "没有设置clientId参数");
		this.clientIdParameter = clientIdParameter;
	}

	public String getClientSecretParameter() {
		return clientSecretParameter;
	}

	public void setClientSecretParameter(String clientSecretParameter) {
		Assert.hasText(clientIdParameter, "没有设置clientSecret参数");
		this.clientSecretParameter = clientSecretParameter;
	}

	public void setPostOnly(boolean postOnly) {
		this.postOnly = postOnly;
	}

}
